(() => {
    /**
     * 装饰器：装饰器是一种特殊类型的声明，它能够被附加到类声明，方法，属性或参数上，可以修改类的行为
     * 
     * 通俗的讲装饰器就是一个方法，可以注入到类，方法，属性参数上来扩展类、属性、方法、参数的功能
     * 
     * 常见的装饰器有 ： 类装饰器，属性装饰器，方法装饰器，参数装饰器
     * 
     * 装饰器的写法 ：普通装饰器（无法传参）、装饰器工厂（可传参）
     * 
     */

    // 1.1.类装饰器 (普通装饰器)
    function logClass(target: any) {
        console.log(target);
        target.prototype.apiUrl = '动态扩展的属性'
        target.prototype.run = () => {
            console.log('我是一个run方法');
        }
    }

    @logClass
    class HttpClient {
        constructor() { }
        getData() { }
    }
    const http: any = new HttpClient()
    console.log(http.apiUrl);
    http.run()

    // 1.2.类装饰器（装饰器工厂）
    function logClass2(params: string) {
        return (target: any) => {
            target.prototype.apiUrl = params
        }
    }
    @logClass2('http://ityin.com')
    class HttpClient2 {
        constructor() { }
        getData() { }
    }
    const http2: any = new HttpClient2()
    console.log(http2.apiUrl);


    // 1.3类装饰器，重载构造函数
    function logClass3(target: any) {
        return class extends target {
            apiUrl: string = '我是重载后的数据'
            getData() {
                console.log(this.apiUrl + '重载');
            }
        }
    }
    @logClass3
    class HttpClient3 {
        apiUrl: string
        constructor(apiUrl: string) {
            this.apiUrl = apiUrl
        }
        getData() {
            console.log(this.apiUrl);
        }
    }
    const http3 = new HttpClient3('我是构造函数内的数据')
    console.log(http3.apiUrl);
    http3.getData()


    // 2.属性装饰器
    /**
     * 属性装饰器表达式会在运行是当作函数被调用，传入以下两个参数
     * (1).对于静态成员来说是类的构造函数，对于实例成员来说是类的原型对象
     * 
     * (2).成员名字
     */
    function logProperty(parmas: string) {
        return (target: any, attr: string) => {
            target[attr] = parmas
        }
    }
    class HttpClient4 {
        @logProperty('属性装饰器')
        url: string
        constructor() { }
    }
    const http4 = new HttpClient4()
    console.log(http4.url);
})()